package userConfig

import (
	"context"
	"devops-super/api"
	"devops-super/api/configs/v1"
	"devops-super/internal/consts/cacheConsts"
	"devops-super/internal/dao"
	"devops-super/internal/model/entity"
	"devops-super/internal/service"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
)

// sUserConfig 用户配置逻辑实现
type sUserConfig struct{}

func init() {
	service.RegisterUserConfig(New())
}

// New 创建用户配置逻辑实例
func New() *sUserConfig {
	return &sUserConfig{}
}

// GetPageLst 分页获取用户配置列表
func (*sUserConfig) GetPageLst(ctx context.Context, req *v1.UserConfigGetPageLstReq) (out *api.PageLstRes[*entity.UserConfig], err error) {
	out = &api.PageLstRes[*entity.UserConfig]{}
	m := dao.UserConfig.Ctx(ctx).Safe(true)

	// 用户ID筛选
	if req.UserId > 0 {
		m = m.Where(dao.UserConfig.Columns().UserId, req.UserId)
	}

	// 配置组名筛选
	if req.GroupName != "" {
		m = m.Where(dao.UserConfig.Columns().GroupName, req.GroupName)
	}

	// 配置键筛选
	if req.ConfigKey != "" {
		m = m.Where(dao.UserConfig.Columns().ConfigKey+" like ? ", "%"+req.ConfigKey+"%")
	}

	// 分页查询
	err = m.Offset(req.Offset()).Limit(req.Limit()).ScanAndCount(&out.List, &out.Total, false)
	return
}

// Add 新增用户配置
func (*sUserConfig) Add(ctx context.Context, in *entity.UserConfig) (err error) {
	// 检查用户+配置组+配置键是否已存在
	count, _ := dao.UserConfig.Ctx(ctx).Where(dao.UserConfig.Columns().UserId, in.UserId).
		Where(dao.UserConfig.Columns().GroupName, in.GroupName).
		Where(dao.UserConfig.Columns().ConfigKey, in.ConfigKey).Count()
	if count > 0 {
		return errors.New("该用户的配置组下的配置键已存在")
	}

	// 插入配置记录
	_, err = dao.UserConfig.Ctx(ctx).Insert(in)
	return
}

// Upt 更新用户配置
func (*sUserConfig) Upt(ctx context.Context, in *entity.UserConfig) (err error) {
	// 检查用户+配置组+配置键是否已被其他记录使用
	count, _ := dao.UserConfig.Ctx(ctx).Where(dao.UserConfig.Columns().UserId, in.UserId).
		Where(dao.UserConfig.Columns().GroupName, in.GroupName).
		Where(dao.UserConfig.Columns().ConfigKey, in.ConfigKey).
		Where(dao.UserConfig.Columns().Id, "!=", in.Id).Count()
	if count > 0 {
		return errors.New("该用户的配置组下的配置键已存在")
	}

	// 更新配置记录
	_, err = dao.UserConfig.Ctx(ctx).WherePri(in.Id).OmitNilData().Data(in).Update()
	return
}

// Del 删除用户配置
func (*sUserConfig) Del(ctx context.Context, id int) (err error) {
	// 先查询配置信息
	config := &entity.UserConfig{}
	err = dao.UserConfig.Ctx(ctx).WherePri(id).Scan(config)
	if err != nil || config.Id == 0 {
		return errors.New("配置不存在")
	}
	// 删除缓存
	cacheKey := cacheConsts.GetUserConfigKey(config.UserId, config.GroupName, config.ConfigKey)
	_, _ = service.GetCacheInstance().Remove(ctx, cacheKey)
	// 删除配置
	_, err = dao.UserConfig.Ctx(ctx).WherePri(id).Delete()
	return
}

// GetOne 获取单条用户配置
func (*sUserConfig) GetOne(ctx context.Context, id int) (out *entity.UserConfig, err error) {
	out = &entity.UserConfig{}
	err = dao.UserConfig.Ctx(ctx).WherePri(id).Scan(&out)
	return
}

// GetOptions 获取用户配置选项
func (*sUserConfig) GetOptions(ctx context.Context, req *v1.UserConfigGetOptionsReq) (out *v1.UserConfigGetOptionsRes, err error) {
	var data []*entity.UserConfig
	m := dao.UserConfig.Ctx(ctx)

	// 用户ID筛选
	if req.UserId > 0 {
		m = m.Where(dao.UserConfig.Columns().UserId, req.UserId)
	}

	// 配置组名筛选
	if req.GroupName != "" {
		m = m.Where(dao.UserConfig.Columns().GroupName, req.GroupName)
	}

	if err = m.Scan(&data); err != nil {
		return
	}

	out = new(v1.UserConfigGetOptionsRes)
	out.Options = make([]*api.FormOptionsItem, 0, len(data))

	// 默认value字段和label字段
	valueField := "id"
	labelField := "configKey"

	// 自定义字段
	if req.FieldKey != "" {
		valueField = req.FieldKey
	}
	if req.FieldLabel != "" {
		labelField = req.FieldLabel
	}

	// 构建选项列表
	for _, v := range data {
		item := &api.FormOptionsItem{}
		// 根据反射获取自定义字段值
		if valueField == "id" {
			item.Value = v.Id
		} else if valueField == "configKey" {
			item.Value = v.ConfigKey
		} else if valueField == "configValue" {
			item.Value = v.ConfigValue
		} else {
			item.Value = v.Id
		}

		if labelField == "configKey" {
			item.Label = v.ConfigKey
		} else if labelField == "configValue" {
			item.Label = v.ConfigValue
		} else if labelField == "groupName" {
			item.Label = v.GroupName
		} else {
			item.Label = v.ConfigKey
		}

		out.Options = append(out.Options, item)
	}

	return
}

// GetGroupConfigs 获取配置组
func (*sUserConfig) GetGroupConfigs(ctx context.Context, in *v1.GetGroupConfigsReq) (out *v1.GetGroupConfigsRes, err error) {
	out = &v1.GetGroupConfigsRes{}

	// 查询配置项
	err = dao.UserConfig.Ctx(ctx).
		Where(dao.UserConfig.Columns().UserId, in.UserId).
		Where(dao.UserConfig.Columns().GroupName, in.GroupName).
		Order(dao.UserConfig.Columns().Id).
		Scan(&out.Configs)
	if err != nil {
		return nil, err
	}

	// 获取最新更新时间
	if len(out.Configs) > 0 {
		latestTime := out.Configs[0].UpdatedAt
		for _, item := range out.Configs {
			if item.UpdatedAt.After(latestTime) {
				latestTime = item.UpdatedAt
			}
		}
		out.UpdatedAt = latestTime.Format("2006-01-02 15:04:05")
	}

	return out, nil
}

// SetGroupConfigs 保存配置组
func (*sUserConfig) SetGroupConfigs(ctx context.Context, in *v1.SetGroupConfigsReq) (err error) {
	// 使用事务确保数据一致性
	tx, err := g.DB().Begin(ctx)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	// 删除用户下指定组的现有配置
	_, err = dao.UserConfig.Ctx(ctx).
		TX(tx).
		Where(dao.UserConfig.Columns().UserId, in.UserId).
		Where(dao.UserConfig.Columns().GroupName, in.GroupName).
		Delete()
	if err != nil {
		return err
	}

	// 批量添加新配置
	for _, item := range in.Configs {
		// 唯一性校验
		exists, err := dao.UserConfig.Ctx(ctx).
			TX(tx).
			Where(g.Map{
				dao.UserConfig.Columns().UserId:    in.UserId,
				dao.UserConfig.Columns().GroupName: in.GroupName,
				dao.UserConfig.Columns().ConfigKey: item.ConfigKey,
			}).Count()
		if err != nil {
			return err
		}
		if exists > 0 {
			return errors.New(fmt.Sprintf("配置键 %s 已存在", item.ConfigKey))
		}

		// 插入新配置
		_, err = dao.UserConfig.Ctx(ctx).TX(tx).Insert(&entity.UserConfig{
			UserId:      int64(in.UserId),
			GroupName:   in.GroupName,
			ConfigKey:   item.ConfigKey,
			ConfigValue: item.ConfigValue,
			Remark:      item.ConfigDesc,
			CreatedAt:   gtime.Now(),
			UpdatedAt:   gtime.Now(),
		})
		if err != nil {
			return err
		}
		cacheKey := cacheConsts.GetUserConfigKey(int64(in.UserId), in.GroupName, item.ConfigKey)
		_ = service.GetCacheInstance().Set(ctx, cacheKey, item.ConfigValue, 0)
	}

	return nil
}

// GetConfigByKey 根据用户ID、分组名和键名获取配置（优先从缓存读取）
func (*sUserConfig) GetConfigByKey(ctx context.Context, userId int64, groupName string, configKey string) (configValue string, err error) {
	cacheKey := cacheConsts.GetUserConfigKey(userId, groupName, configKey)
	// 先从缓存读取
	if v, err := service.GetCacheInstance().Get(ctx, cacheKey); err == nil && !v.IsEmpty() {
		return v.String(), nil
	}

	// 缓存未命中则查数据库
	config := new(entity.UserConfig)
	err = dao.UserConfig.Ctx(ctx).
		Where(dao.UserConfig.Columns().UserId, userId).
		Where(dao.UserConfig.Columns().GroupName, groupName).
		Where(dao.UserConfig.Columns().ConfigKey, configKey).
		Scan(&config)

	if err != nil || config.Id == 0 {
		return "", errors.New("配置不存在")
	}

	// 设置缓存
	_ = service.GetCacheInstance().Set(ctx, cacheKey, config.ConfigValue, 0)

	return config.ConfigValue, nil
}
